#include<iostream>
#include<vector>
#include<string>
using namespace std;

class Solution {
public:

    int dp[110][110];

    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        int m, n;
        m = obstacleGrid.size();
        n = obstacleGrid[0].size();
        dp[0][1] = 1;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (obstacleGrid[i][j] != 1) {
                    dp[i + 1][j + 1] = dp[i][j + 1] + dp[i + 1][j];
                }
            }
        }
        return dp[m][n];
    }
};

class Solution {
public:

    int jewelleryValue(vector<vector<int>>& frame) {
        int m = frame.size();
        int n = frame[0].size();
        vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                dp[i][j] = frame[i - 1][j - 1] + max(dp[i - 1][j], dp[i][j - 1]);
            }
        }
        return dp[m][n];
    }
};

class Solution {
public:
    int minFallingPathSum(vector<vector<int>>& matrix) {
        int m = matrix.size();
        int n = matrix[0].size();
        vector<vector<int>> dp(m + 1, vector<int>(n + 2, 0));
        for (int i = 0; i < m; i++) {
            dp[i][0] = INT_MAX;
            dp[i][n + 1] = INT_MAX;
        }
        for (int i = 1; i < m; i++) {
            for (int j = 1; j <= n; j++) {
                dp[i][j] = min(min(dp[i - 1][j - 1], dp[i - 1][j + 1]), dp[i - 1][j]) + matrix[i - 1][j - 1];
            }
        }
        int ans = INT_MAX;
        for (int j = 1; j <= n; j++) {
            ans = min(ans, min(min(dp[m - 1][j - 1], dp[m - 1][j + 1]), dp[m - 1][j]) + matrix[m - 1][j - 1]);
        }
        return ans;
    }
};

class Solution {
public:
    int minPathSum(vector<vector<int>>& grid) {
        int m = grid.size();
        int n = grid[0].size();
        vector<vector<int>> dp(m + 1, vector<int>(n + 1, INT_MAX));
        dp[0][1] = 0;
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + grid[i - 1][j - 1];
            }
        }
        return dp[m][n];
    }
};

class Solution {
public:
    int calculateMinimumHP(vector<vector<int>>& dungeon) {
        int m = dungeon.size();
        int n = dungeon[0].size();
        vector<vector<int>> dp(m + 1, vector<int>(n + 1, INT_MAX));
        dp[m][n - 1] = 1;
        for (int i = m - 1; i >= 0; i--) {
            for (int j = n - 1; j >= 0; j--) {
                dp[i][j] = max(min(dp[i][j + 1], dp[i + 1][j]) - dungeon[i][j], 1);
            }
        }
        return dp[0][0];
    }
};